﻿using System;
using System.Collections.Generic;
using System.Linq;
using Hopscotch.Domain.Common;
using Hopscotch.Domain.Common.StateTracking;


namespace Hopscotch.Server.AppServiceFake
{
    public abstract class FakeServiceIntKey<T> : FakeServiceBase<T, int>
        where T : DomainBase<int>, IObjectWithChangeTracker
    {
        private static Dictionary<int, T> fakeData = new Dictionary<int, T>();

        protected IDictionary<int, T> FakeData
        {
            get
            {
                return fakeData;
            }
        }

        protected void ResetObjectState()
        {
            foreach (var entity in FakeData.Values)
            {
                entity.ChangeTracker.State = ObjectState.Unchanged;
            }
        }

        protected void Add(T entity)
        {
            fakeData.Add(entity.Id, entity);
        }


        private void CheckAndSetId(T entity)
        {
            int id = entity.Id;
            if (entity.ChangeTracker.State == ObjectState.Added)
            {
                id = Math.Max(FakeData.Max(s => s.Key), 0) + 1;
                entity.Id = id;
            }
        }

        public override T Save(T entity)
        {
            FakeDelay();

            try
            {
                if (!entity.IsValid)
                    throw new ApplicationException(string.Format("{0} is not valid. {1}", EntityType, entity.Error));

                CheckAndSetId(entity);
                fakeData[entity.Id] = entity;

                entity.ChangeTracker.State = ObjectState.Unchanged;

                return entity;
            }
            catch (Exception ex)
            {
                throw new ApplicationException(string.Format("Error saving {0}", EntityType), ex);
            }
        }

        public override T Get(int id)
        {
            T entity = default(T);
            fakeData.TryGetValue(id, out entity);

            if (entity != null)
            {
                //Reset state to Unchanged to mimic db load
                entity.ChangeTracker.State = Domain.Common.StateTracking.ObjectState.Unchanged;
            }

            return entity;
        }

        public override void Delete(T entity)
        {
            var key = entity.Id;
            if (fakeData.ContainsKey(key))
            {
                fakeData.Remove(key);
            }

            entity.ChangeTracker.State = ObjectState.Deleted;
        }

    }
}
